"""
rttopt.views

Views to define rttopt functions.

@author: as
"""

from jackson import debug

debug.pre_import(__name__)

from time import time
import urllib

from django.template.loader import render_to_string
from django.http import HttpResponse, HttpResponseRedirect

import jackson.extjson.ext_json as json
from jackson.chord import Server
from jackson.chord.db import get_me
from jackson.cdn.admin_api import leave_net as leave_cdn_net
import jackson.rttopt.server_api as server_api
from jackson.rttopt.net import send_rtt_update, lookup
from jackson.fileserverwidget.views import download, upload
from jackson.views import sup
from jackson.rttopt import db

debug.post_import(__name__)

def leave_net(request):
    """ invoke a leave (this server is leaving)
    (this is probably an admin view. )
    """
    context = [__name__, "(the view) leave_net()"]
    debug.enter(context,None)
    try:
        server_api.leave_net()
        r = True
    except Exception, e:
        r = False
        debug.exception(context,str(e))
    try:
        leave_cdn_net()
        r = True
    except Exception, e:
        r = False
        debug.exception(context,"cdn failed to quit, called from rttopt.views. error: " + str(e))
    debug.leave(context,None)
    return HttpResponseRedirect("/sup")

def leave_handler(request):
    """ handle a leave, forward if necessary based on the response from server_api
    """
    context = [__name__, "(the view) leave_handler()"]
    debug.enter(context, None)
    debug.comment(context,'loading the request data:')
    r = request.POST['data']
    data = json.loads(r)
    s = data['server']
    t = data['timestamp']
    debug.comment(context,'calling the leave_handler')
    try:
        b = server_api.leave_handler(s, t)
    except Exeption, e:
        debug.exception(context,"issue with server_api.leave_handler(): " + str(e))
    debug.leave(context, None)
    return HttpResponse(json.dumps(b), mimetype="application/json")

def lookup_handler(request):
    """
    Handles an RTT lookup request.  
    @param request: an HTTP request containing JSONified dict with 'key' as a key
    @see jackson.rttop.server_api.lookup_handler
    """
    context = [__name__, "lookup_handler()"]
    debug.enter(context, None)
    data = json.loads(request.POST['data'])
    key = data['key']
    debug.comment(context, "passing our key to server_api")
    r = False # our response
    try:
        d = server_api.lookup_handler(key)
        if 'redirect' in d:
            # we are redirecting
            debug.comment(context,"redirecting")
            r = HttpResponseRedirect(d['redirect'])
        else:
            j = json.dumps({'server' : d['server'], 'rtt':d['rtt']})
            debug.comment(context,str(j))
            r = HttpResponse(j, mimetype="application/json")
        debug.leave(context, None)
    except Exception, e:
        debug.exception(context,str(e))
    return r


def update_handler(request):
    """
    Handles an RTT update request.
    @param request: an HTTP request
    """
    context = [__name__, "update_handler()"]
    debug.enter(context, None)
    try:
        data = json.loads(request.POST['data'])
        s = data['server']
        rtt = data['rtt']
        key = data['key']
        cstr = data['range']
        a = server_api.update_handler(key,s,rtt,cstr)
    except Exception, e:
        debug.exception(context,str(e))
    debug.leave(context, None)
    return HttpResponse(json.dumps({'success': a}), mimetype="application/json")
    
def timer(request):
    """
    Times the RTT, then redirects to the desired page.
    """
    context = [__name__, "timer()"]
    debug.enter(context, None)
    if request.method == 'GET' and 'time' in request.GET:
        # directly after the initial visit.
        # at this point, we want to redirect the client (again), this time to a node that 
        # we know has a fast time.
        
        # perform a lookup, 
        # redirect to this server + request.GET['path']
        
        me = get_me()
        debug.comment(context, str(request.GET))
        debug.comment(context, "calculating and recording a new RTT. ")
        ip = request.GET['addr']
        
        # 8000 will have a large delay when talking to local (127.0.0.1 servers)
        # 8001 will have a large delay when talking to anyone else
        
        debug.comment(context,"my port is ")
        if me.port == 8000 and (ip == "127.0.0.1" or ip=="192.168.1.1"):
            debug.comment(context,"slowing down port 8000 server's response. sleeping for one second")
            from time import sleep
            sleep(1)
        elif me.port == 8001 and ip != "127.0.0.1":
            debug.comment(context,"slowing down 8001 server's response, sleeping for one second")
            from time import sleep
            sleep(1)
        
        
        rtt = time() - float(request.GET['time'])
        send_rtt_update(rtt, ip)
        debug.comment(context,"we've sent out the rtt update. now seeing who is the fastest.")
        fast_guy = lookup(ip)
        if fast_guy == False or (me.ip == fast_guy.ip and me.port == fast_guy.port):
            debug.comment(context,"just serve the response, i'm closest to the client")
            a = forward(request,request.GET['path'])
            debug.comment(context, "used forward() to complete the initial GET request")
        else:
            # check to see if we are given an absolute path, or an empty path of some kind.
            # we need an extra "/" then
            if (len(str(request.GET['path'])) == 0) or (request.GET['path'][0] != '/'):
                debug.comment(context,"path wasn't absolute.")
                new_url = "http://" + fast_guy.ip + ":" + str(fast_guy.port) + "/" + request.GET['path']
            else:
                new_url = "http://" + fast_guy.ip + ":" + str(fast_guy.port) + request.GET['path']
            debug.comment(context,"forwarding to " + new_url + ". hopefully this works")
            a = HttpResponseRedirect(new_url)
            debug.comment(context, "trying to forward us to the right server,")
        debug.leave(context, None)
        return a
    elif request.method == 'POST':
        # probably after we've gotten the RTT, they submit what they want.
        # we can assume at this point, rttopt has directed them to the right place.
        debug.comment(context,"forwarding a POST request to the proper place: " + 
                      request.META['REQUEST_URI'])
        a = forward(request, request.META['REQUEST_URI'])
        debug.leave(context, None)
        return a
    else:
        # this is the initial client request for a page like /download.
        debug.comment(context,
             "forwarding a GET(?) request to myself, with the time embedded.")
        debug.comment(context,"original non-POST request_uri: " + 
                      request.META['REQUEST_URI'])
        path = request.META['REQUEST_URI']
        ip = request.META['REMOTE_ADDR']
        params = urllib.urlencode({'path': path, 'addr': ip, 'time': time()})
        newurl = '/rttopt/timer?' + params
        debug.leave(context, {"newurl":newurl})
        return HttpResponseRedirect(newurl)

def forward(request, path):
    context = [__name__, "forward()"]
    debug.enter(context, None)
    debug.comment(context, "switching off request path: " + path)
    if path == "/upload":
        debug.comment(context, "passing the response over to fsw.views.upload(). ")
        r = upload(request)
        debug.leave(context, None)
        return r
    elif path == "/download":
        a = download(request)        
        debug.leave(context, None)
        return a
    elif path == "/sup":
        a = sup(request)
        debug.leave(context, None)
        return a
    else:
        r = render_to_string("base.html",
                                {'title': "404",
                                 'content': "Path " + path + " NOT FOUND"})
        debug.leave(context, None)
        return HttpResponse(r)


def dump_handler(request):
    ip_list = db.list_ip_dbs()
    lines = []
    for ipdb in ip_list:
        lines.append(ipdb[1])
        for row in db.lookup_IP_table(ipdb[0]):
            lines.append('\t' + str(row[0]) + ': ' + str(row[1]))
        lines.append('==================================================================================')
    lines.append('Goodbye, and thanks for all the fish')
    return HttpResponse(render_to_string('base.html',
                                         {'centered_title': 'ip table dump',
                                          'content': lines,
                                          'content_is_list': True}))
